﻿#region Legal notice
/*
 * This file is part of EPPLib.
 * Copyright 2010, 2011 
 * Gianluca Esposito (info@gianlucaesposito.it)
 * ----------------------------------------------------------------------------
 * EPPLib is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 * 
 * EPPLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Nome-Programma; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Web;
using EPPLib.Data;
using EPPLib.Messages;

namespace EPPLib.Managers
{
    public class ServiceManager : IServiceManager
    {
        #region Enum
        public enum AccreditationUsers
        {
            UserA,
            UserB
        }
        #endregion

        #region Constants
        private const string SERVER_SESSION_COOKIE = "__SERVER_SESSION_COOKIE";
        private const string ISAUTHENTICATED = "__ISAUTHENTICATED";

        private const string SERVER_SESSION_COOKIE_A = "__SERVER_SESSION_COOKIE_A";
        private const string SERVER_SESSION_COOKIE_B = "__SERVER_SESSION_COOKIE_B";
        private const string ISAUTHENTICATED_A = "__ISAUTHENTICATED_A";
        private const string ISAUTHENTICATED_B = "__ISAUTHENTICATED_B";
        private const string SERVER_SESSION_USER_A = "__SERVER_SESSION_USER_A";
        private const string SERVER_SESSION_USER_B = "__SERVER_SESSION_USER_B";
        private const string SERVER_SESSION_PASSWORD_A = "__SERVER_SESSION_PASSWORD_A";
        private const string SERVER_SESSION_PASSWORD_B = "__SERVER_SESSION_PASSWORD_B";
        private const string SERVER_SESSION_ACCREDITATION_URL = "__SERVER_SESSION_ACCREDITATION_URL";
        #endregion

        #region Members
        private Guid _currentUserID;
        #endregion

        #region Properties
        public Guid CurrentUserID
        {
            get { return _currentUserID; }
            set { _currentUserID = value; }
        }
        public string Session
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_COOKIE] != null) return HttpContext.Current.Session[SERVER_SESSION_COOKIE].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_COOKIE] = value;
            }
        }
        public bool IsAuthenticated
        {
            get
            {
                if (HttpContext.Current.Session[ISAUTHENTICATED] != null) return (bool)HttpContext.Current.Session[ISAUTHENTICATED];
                return false;
            }
            set
            {
                HttpContext.Current.Session[ISAUTHENTICATED] = value;
            }
        }

        public string AccreditationUrl
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_ACCREDITATION_URL] != null) return HttpContext.Current.Session[SERVER_SESSION_ACCREDITATION_URL].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_ACCREDITATION_URL] = value;
            }
        }

        public string UserA
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_USER_A] != null) return HttpContext.Current.Session[SERVER_SESSION_USER_A].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_USER_A] = value;
            }
        }
        public string PasswordA
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_PASSWORD_A] != null) return HttpContext.Current.Session[SERVER_SESSION_PASSWORD_A].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_PASSWORD_A] = value;
            }
        }
        public string SessionA
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_COOKIE_A] != null) return HttpContext.Current.Session[SERVER_SESSION_COOKIE_A].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_COOKIE_A] = value;
            }
        }
        public bool IsAuthenticatedA
        {
            get
            {
                if (HttpContext.Current.Session[ISAUTHENTICATED_A] != null) return (bool)HttpContext.Current.Session[ISAUTHENTICATED_A];
                return false;
            }
            set
            {
                HttpContext.Current.Session[ISAUTHENTICATED_A] = value;
            }
        }

        public string UserB
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_USER_B] != null) return HttpContext.Current.Session[SERVER_SESSION_USER_B].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_USER_B] = value;
            }
        }
        public string PasswordB
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_PASSWORD_B] != null) return HttpContext.Current.Session[SERVER_SESSION_PASSWORD_B].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_PASSWORD_B] = value;
            }
        }
        public string SessionB
        {
            get
            {
                if (HttpContext.Current.Session[SERVER_SESSION_COOKIE_B] != null) return HttpContext.Current.Session[SERVER_SESSION_COOKIE_B].ToString();
                return string.Empty;
            }
            set
            {
                HttpContext.Current.Session[SERVER_SESSION_COOKIE_B] = value;
            }
        }
        public bool IsAuthenticatedB
        {
            get
            {
                if (HttpContext.Current.Session[ISAUTHENTICATED_B] != null) return (bool)HttpContext.Current.Session[ISAUTHENTICATED_B];
                return false;
            }
            set
            {
                HttpContext.Current.Session[ISAUTHENTICATED_B] = value;
            }
        }
        #endregion

        public ServiceManager()
        {
            if (string.IsNullOrEmpty(Session))
                Session = string.Empty;
            if (string.IsNullOrEmpty(SessionA))
                SessionA = string.Empty;
            if (string.IsNullOrEmpty(SessionB))
                SessionB = string.Empty;
            // IsAuthenticated = false;
            _currentUserID = Guid.Empty;
        }

        protected bool OnCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        public void ClearSession()
        {
            Session = string.Empty;
            IsAuthenticated = false;
        }

        public void ClearAccreditationSessionA()
        {
            SessionA = string.Empty;
            IsAuthenticatedA = false;
        }

        public void ClearAccreditationSessionB()
        {
            SessionB = string.Empty;
            IsAuthenticatedB = false;
        }

        public string Request(string url, string data, string clientTransactionID = "")
        {
            string responseData = string.Empty;
            WebRequest request = WebRequest.Create(url);
            request.Method = "POST";
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(this.OnCertificateValidation);
            request.ContentType = "text/xml";

            if (!string.IsNullOrEmpty(Session))
            {
                request.Headers.Add("Cookie", Session);
            }

            try
            {
                StreamWriter writer = new StreamWriter(request.GetRequestStream());
                writer.WriteLine(NormalizeRequest(data));
                writer.Close();
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    if (string.IsNullOrEmpty(Session))
                    {
                        Session = response.Headers["Set-Cookie"];
                    }
                    StreamReader sr = new StreamReader(response.GetResponseStream());
                    responseData = sr.ReadToEnd();
                }
            }
            catch (Exception exception)
            {
                throw new ApplicationException(exception.Message, exception);
            }

            // Save transaction log item
            try
            {
                TransactionLogDataObject transactionLog = new TransactionLogDataObject();
                transactionLog.OwnerID = _currentUserID;
                transactionLog.ClientTransactionID = clientTransactionID;
                try
                {
                    BaseResponseMessage responseMessage = new BaseResponseMessage();
                    responseMessage = (BaseResponseMessage)responseMessage.Deserialize(responseData);
                    transactionLog.ServerTransactionID = responseMessage.Response.TransactionID.ServerTransactionID;
                    transactionLog.ClientTransactionID = responseMessage.Response.TransactionID.ClientTransactionID;
                }
                catch
                {
                    // DO NOTHING
                }
                transactionLog.RequestRawData = NormalizeRequest(data);
                transactionLog.ResponseRawData = responseData;
                transactionLog.Session = Session;
                transactionLog.TargetUrl = url;
                transactionLog.TransactionDate = DateTime.Now;
                DataManager manager = new DataManager();
                manager.SaveTransactionLog(transactionLog);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(ex.Message, ex);
            }

            return responseData;
        }

        public string AccreditationRequest(string url, string data, AccreditationUsers user, string clientTransactionID = "")
        {
            string responseData = string.Empty;
            WebRequest request = WebRequest.Create(url);
            request.Method = "POST";
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(this.OnCertificateValidation);
            request.ContentType = "text/xml";

            switch (user) {
                case AccreditationUsers.UserA :
                    if (!string.IsNullOrEmpty(SessionA))
                    {
                        request.Headers.Add("Cookie", SessionA);
                    }
                    break;
                case AccreditationUsers.UserB :
                    if (!string.IsNullOrEmpty(SessionB))
                    {
                        request.Headers.Add("Cookie", SessionB);
                    }
                    break;
            }
            try
            {
                StreamWriter writer = new StreamWriter(request.GetRequestStream());
                writer.WriteLine(NormalizeRequest(data));
                writer.Close();
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    switch (user)
                    {
                        case AccreditationUsers.UserA:
                            if (string.IsNullOrEmpty(SessionA))
                            {
                                SessionA = response.Headers["Set-Cookie"];
                            }
                            break;
                        case AccreditationUsers.UserB:
                            if (string.IsNullOrEmpty(SessionB))
                            {
                                SessionB = response.Headers["Set-Cookie"];
                            }
                            break;
                    }

                    StreamReader sr = new StreamReader(response.GetResponseStream());
                    responseData = sr.ReadToEnd();
                }
            }
            catch (Exception exception)
            {
                throw new ApplicationException(exception.Message, exception);
            }

            // Save transaction log item
            try
            {
                TransactionLogDataObject transactionLog = new TransactionLogDataObject();
                transactionLog.OwnerID = _currentUserID;
                transactionLog.ClientTransactionID = clientTransactionID;
                try
                {
                    BaseResponseMessage responseMessage = new BaseResponseMessage();
                    responseMessage = (BaseResponseMessage)responseMessage.Deserialize(responseData);
                    transactionLog.ServerTransactionID = responseMessage.Response.TransactionID.ServerTransactionID;
                    transactionLog.ClientTransactionID = responseMessage.Response.TransactionID.ClientTransactionID;
                }
                catch
                {
                    // DO NOTHING
                }
                transactionLog.RequestRawData = NormalizeRequest(data);
                transactionLog.ResponseRawData = responseData;
                transactionLog.Session = Session;
                transactionLog.TargetUrl = url;
                transactionLog.TransactionDate = DateTime.Now;
                DataManager manager = new DataManager();
                manager.SaveTransactionLog(transactionLog);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(ex.Message, ex);
            }

            return responseData;
        }

        public LoginResponseMessage Login(string url, LoginMessage message)
        {
            MessageContainer container = new MessageContainer();
            container.Command = message;
            container.Type = MessageContainer.CommandTypes.Login;
            string requestData = container.ToString();
            string responseData = Request(url, requestData);
            LoginResponseMessage retObj = new LoginResponseMessage();
            retObj = (LoginResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public LoginResponseMessage AccreditationLogin(string url, LoginMessage message, AccreditationUsers user)
        {
            MessageContainer container = new MessageContainer();
            container.Command = message;
            container.Type = MessageContainer.CommandTypes.Login;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(url, requestData, user);

            LoginResponseMessage retObj = new LoginResponseMessage();
            retObj = (LoginResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public LogoutResponseMessage Logout(string url, LogoutMessage message)
        {
            MessageContainer container = new MessageContainer();
            container.Command = message;
            container.Type = MessageContainer.CommandTypes.Logout;
            string requestData = container.ToString();
            string responseData = Request(url, requestData);
            LogoutResponseMessage retObj = new LogoutResponseMessage();
            retObj = (LogoutResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public LogoutResponseMessage AccreditationLogout(string url, LogoutMessage message, AccreditationUsers user)
        {
            MessageContainer container = new MessageContainer();
            container.Command = message;
            container.Type = MessageContainer.CommandTypes.Logout;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(url, requestData, user);
            LogoutResponseMessage retObj = new LogoutResponseMessage();
            retObj = (LogoutResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public HelloResponseMessage Hello(string url, HelloMessage message)
        {
            MessageContainer container = new MessageContainer();
            container.Command = message;
            container.Type = MessageContainer.CommandTypes.Hello;
            string requestData = container.ToString();
            string responseData = Request(url, requestData);
            HelloResponseMessage retObj = new HelloResponseMessage();
            retObj = (HelloResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public BaseResponseMessage CreateContact(string url, CreateContactMessage message, CreateExtendedContactMessage extendedMessage, string clientTransactionID)
        {
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (extendedMessage != null)
                container.Extension = extendedMessage;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Create;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            BaseResponseMessage retObj = new BaseResponseMessage();
            retObj = (BaseResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CreateContactResponseMessage CreateContact(string url, string username, string password, CreateContactMessage message, CreateExtendedContactMessage extendedMessage, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (extendedMessage != null)
                container.Extension = extendedMessage;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Create;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            CreateContactResponseMessage retObj = new CreateContactResponseMessage();
            retObj = (CreateContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CreateContactResponseMessage AccreditationCreateContact(AccreditationUsers user, CreateContactMessage message, CreateExtendedContactMessage extendedMessage, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (extendedMessage != null)
                container.Extension = extendedMessage;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Create;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            CreateContactResponseMessage retObj = new CreateContactResponseMessage();
            retObj = (CreateContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CheckContactResponseMessage CheckContact(string url, string username, string password, CheckContactMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Check;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            CheckContactResponseMessage retObj = new CheckContactResponseMessage();
            retObj = (CheckContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CheckContactResponseMessage AccreditationCheckContact(AccreditationUsers user, CheckContactMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Check;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            CheckContactResponseMessage retObj = new CheckContactResponseMessage();
            retObj = (CheckContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public InfoContactResponseMessage InfoContact(string url, string username, string password, InfoContactMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Info;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            InfoContactResponseMessage retObj = new InfoContactResponseMessage();
            retObj = (InfoContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public InfoContactResponseMessage AccreditationInfoContact(AccreditationUsers user, InfoContactMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Info;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            InfoContactResponseMessage retObj = new InfoContactResponseMessage();
            retObj = (InfoContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public UpdateContactResponseMessage UpdateContact(string url, string username, string password, UpdateContactMessage message, UpdateExtendedContactMessage extendedMessage, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            if (extendedMessage != null)
                container.Extension = extendedMessage;

            container.Type = MessageContainer.CommandTypes.Update;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            UpdateContactResponseMessage retObj = new UpdateContactResponseMessage();
            retObj = (UpdateContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public UpdateContactResponseMessage AccreditationUpdateContact(AccreditationUsers user, UpdateContactMessage message, UpdateExtendedContactMessage extendedMessage, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            // Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            if (extendedMessage != null)
                container.Extension = extendedMessage;

            container.Type = MessageContainer.CommandTypes.Update;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            UpdateContactResponseMessage retObj = new UpdateContactResponseMessage();
            retObj = (UpdateContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public DeleteContactResponseMessage DeleteContact(string url, string username, string password, DeleteContactMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Delete;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            DeleteContactResponseMessage retObj = new DeleteContactResponseMessage();
            retObj = (DeleteContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public DeleteContactResponseMessage AccreditationDeleteContact(AccreditationUsers user, DeleteContactMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Delete;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            DeleteContactResponseMessage retObj = new DeleteContactResponseMessage();
            retObj = (DeleteContactResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CheckDomainResponseMessage CheckDomain(string url, string username, string password, CheckDomainMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Check;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            CheckDomainResponseMessage retObj = new CheckDomainResponseMessage();
            retObj = (CheckDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CheckDomainResponseMessage AccreditationCheckDomain(AccreditationUsers user, CheckDomainMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Check;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            CheckDomainResponseMessage retObj = new CheckDomainResponseMessage();
            retObj = (CheckDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public InfoDomainResponseMessage InfoDomain(string url, string username, string password, InfoDomainMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Info;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            InfoDomainResponseMessage retObj = new InfoDomainResponseMessage();
            retObj = (InfoDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public InfoDomainResponseMessage AccreditationInfoDomain(AccreditationUsers user, InfoDomainMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Info;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            InfoDomainResponseMessage retObj = new InfoDomainResponseMessage();
            retObj = (InfoDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CreateDomainResponseMessage CreateDomain(string url, string username, string password, CreateDomainMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;

            container.Type = MessageContainer.CommandTypes.Create;

            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            CreateDomainResponseMessage retObj = new CreateDomainResponseMessage();
            retObj = (CreateDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public CreateDomainResponseMessage AccreditationCreateDomain(AccreditationUsers user, CreateDomainMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;

            container.Type = MessageContainer.CommandTypes.Create;

            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            CreateDomainResponseMessage retObj = new CreateDomainResponseMessage();
            retObj = (CreateDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public UpdateDomainResponseMessage UpdateDomain(string url, string username, string password, UpdateDomainMessage message, UpdateExtendedDomainMessage extendedMessage, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            if (extendedMessage != null)
                container.Extension = extendedMessage;
            container.Type = MessageContainer.CommandTypes.Update;

            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            UpdateDomainResponseMessage retObj = new UpdateDomainResponseMessage();
            retObj = (UpdateDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public UpdateDomainResponseMessage AccreditationUpdateDomain(AccreditationUsers user, UpdateDomainMessage message, UpdateExtendedDomainMessage extendedMessage, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            if (extendedMessage != null)
                container.Extension = extendedMessage;
            container.Type = MessageContainer.CommandTypes.Update;

            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            UpdateDomainResponseMessage retObj = new UpdateDomainResponseMessage();
            retObj = (UpdateDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public TransferDomainResponseMessage TransferDomain(string url, string username, string password, MessageContainer.Operations operation, TransferDomainMessage message, TransferExtendedDomainMessage extendedMessage, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            if (extendedMessage != null)
                container.Extension = extendedMessage;

            container.Type = MessageContainer.CommandTypes.Transfer;
            container.Operation = operation;

            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            TransferDomainResponseMessage retObj = new TransferDomainResponseMessage();
            retObj = (TransferDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public TransferDomainResponseMessage AccreditationTransferDomain(AccreditationUsers user, MessageContainer.Operations operation, TransferDomainMessage message, TransferExtendedDomainMessage extendedMessage, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            if (extendedMessage != null)
                container.Extension = extendedMessage;

            container.Type = MessageContainer.CommandTypes.Transfer;
            container.Operation = operation;

            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            TransferDomainResponseMessage retObj = new TransferDomainResponseMessage();
            retObj = (TransferDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public DeleteDomainResponseMessage DeleteDomain(string url, string username, string password, DeleteDomainMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Delete;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            DeleteDomainResponseMessage retObj = new DeleteDomainResponseMessage();
            retObj = (DeleteDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public DeleteDomainResponseMessage AccreditationDeleteDomain(AccreditationUsers user, DeleteDomainMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Delete;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            DeleteDomainResponseMessage retObj = new DeleteDomainResponseMessage();
            retObj = (DeleteDomainResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public PollRequestResponseMessage PollRequest(string url, string username, string password, PollRequestMessage message, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Poll;
            container.Operation = MessageContainer.Operations.Request;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            PollRequestResponseMessage retObj = new PollRequestResponseMessage();
            retObj = (PollRequestResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public BaseResponseMessage PollAcknownledgment(string url, string username, string password, string messageID, string clientTransactionID)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            Login(url, username, password);
            MessageContainer container = new MessageContainer();
            container.Command = new PollAcknowledgmentMessage();
            container.Extension = null;
            container.MessageID = messageID;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Poll;
            container.Operation = MessageContainer.Operations.Acknownledgment;
            string requestData = container.ToString();
            string responseData = Request(url, requestData, clientTransactionID);
            BaseResponseMessage retObj = new BaseResponseMessage();
            retObj = (BaseResponseMessage)retObj.Deserialize(requestData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public BaseResponseMessage AccreditationPollAcknownledgment(AccreditationUsers user, string messageID, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = new PollAcknowledgmentMessage();
            container.Extension = null;
            container.MessageID = messageID;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Poll;
            container.Operation = MessageContainer.Operations.Acknownledgment;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            BaseResponseMessage retObj = new BaseResponseMessage();
            retObj = (BaseResponseMessage)retObj.Deserialize(requestData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        public PollRequestResponseMessage AccreditationPollRequest(AccreditationUsers user, PollRequestMessage message, string clientTransactionID)
        {
            // DataManager _dataManager = new DataManager();
            // _dataManager.IncreaseOperationCount(_currentUserID);

            MessageContainer container = new MessageContainer();
            container.Command = message;
            if (!string.IsNullOrEmpty(clientTransactionID))
                container.ClientTransactionID = clientTransactionID;
            container.Type = MessageContainer.CommandTypes.Poll;
            container.Operation = MessageContainer.Operations.Request;
            string requestData = container.ToString();
            string responseData = AccreditationRequest(AccreditationUrl, requestData, user, clientTransactionID);
            PollRequestResponseMessage retObj = new PollRequestResponseMessage();
            retObj = (PollRequestResponseMessage)retObj.Deserialize(responseData);
            retObj.RawRequestData = requestData;
            retObj.RawResponseData = responseData;
            return retObj;
        }

        private void Login(string url, string username, string password)
        {
            DataManager _dataManager = new DataManager();
            _dataManager.IncreaseOperationCount(_currentUserID);

            if (!IsAuthenticated)
            {
                LoginMessage loginRequest = new LoginMessage();
                loginRequest.RegistrarID = username;
                loginRequest.Password = password;
                LoginResponseMessage loginResponse = Login(url, loginRequest);
                if (loginResponse.Response.Status == EPPLib.Objects.ResponseObject.ResponseStatus.Done || loginResponse.Response.Status == Objects.ResponseObject.ResponseStatus.AlreadyLoggedIn)
                    IsAuthenticated = true;
                else
                    IsAuthenticated = false;
            }
        }

        // TO DO: Verificare
        private string NormalizeRequest(string data)
        {
            data = data.Replace("xmlns=\"\"", string.Empty);
            return data;
        }
    }
}